/*
 * MapView.fx
 *
 * Created on Mar 26, 2010, 8:52:51 PM
 */
package com.gpsbuddy.objects;

/**
 * @author jonycus
 */
import javafx.scene.CustomNode;
import javafx.scene.Node;
import javafx.scene.input.MouseEvent;
import javafx.scene.Group;
import java.lang.Math;
import java.util.HashMap;
import com.gpsbuddy.utils.TilesUtils;

var tileMap: HashMap = new HashMap();

public class MapView extends CustomNode {

    public var z: Integer;
    public var longitude: Double on replace {
                mapX = TilesUtils.getXTile(longitude, z) * 256;
                mapY = TilesUtils.getYTile(lattitude, z) * 256;
                calculateBounds();
            };
    public var lattitude: Double on replace {
                mapX = TilesUtils.getXTile(longitude, z) * 256;
                mapY = TilesUtils.getYTile(lattitude, z) * 256;
                calculateBounds();
            };
    public var width ;
    public var height ;
    public var mapX = TilesUtils.getXTile(longitude, z) * 256;
    public var mapY = TilesUtils.getYTile(lattitude, z) * 256;
    public var mapFixX = mapX;
    public var mapFixY = mapY;
    public var zoom: Integer = z on replace oldzoom {
                if (oldzoom > 0) {
                    println("zoom changed from {oldzoom} to {zoom}");
                    if (zoom > oldzoom) {
                        mapX = mapX * Math.pow(2, zoom - oldzoom) + width / 2 as Integer;
                        mapY = mapY * Math.pow(2, zoom - oldzoom) + height / 2 as Integer;
                    } else {
                        mapX = mapX * Math.pow(2, zoom - oldzoom) - width / 4 as Integer;
                        mapY = mapY * Math.pow(2, zoom - oldzoom) - height / 4 as Integer;
                    }
                    mapFixX = mapX;
                    mapFixY = mapY;
                    calculateBounds();
                }
            };
    var tiles: TileUI[];
    override var onMouseDragged = function (evt: MouseEvent) {
                mapX = mapFixX - (evt.dragX as Integer);
                mapY = mapFixY - (evt.dragY as Integer);
            }
    override var onMouseReleased = function (evt: MouseEvent) {
                mapFixX = mapX;
                mapFixY = mapY;
                calculateBounds();
            }
    override var onMouseWheelMoved = function (evt: MouseEvent) {
                if (evt.wheelRotation < 0) {
                    if (zoom < 18) {
                        zoom++;
                    }
                } else {
                    if (zoom > 1) {
                        zoom--;
                    }
                }
            }

    public function calculateBounds() {
        var bx0: Integer = mapFixX / 256;
        var by0: Integer = mapFixY / 256;
        var hit: Integer = height / 256 as Integer;
        var wit: Integer = width / 256 as Integer;
        var maxidx = Math.pow(2, zoom) - 1 as Integer;
        for (i in [0..hit + 1]) {
            for (j in [0..wit + 1]) {
                var bx = bx0 + j;
                var by = by0 + i;
                var idx: Long = Math.pow(2, 2 * zoom) + bx * Math.pow(2, zoom) + by as Long;
                println(idx);
                if (not tileMap.containsKey(idx)) {

                    if (zoom < 19 and bx > -1 and by > -1 and bx <= maxidx and by <= maxidx) {
                        def myzoom = zoom;
                        var newtile = TileUI {
                                    mapView: this
                                    zoom: myzoom;
                                    x: bx;
                                    y: by;
                                    translateX: bind (bx) * 256 * Math.pow(2, zoom - myzoom) - mapX + 128 * (zoom - myzoom);
                                    translateY: bind (by) * 256 * Math.pow(2, zoom - myzoom) - mapY + 128 * (zoom - myzoom);
                                    scaleX: bind Math.pow(2, zoom - myzoom);
                                    scaleY: bind Math.pow(2, zoom - myzoom);
                                }
                        tileMap.put(idx, newtile);
                        var zoomout = zoom - 1;
                        var pidx: Long = Math.pow(2, 2 * zoomout) + bx / 2 * Math.pow(2, zoomout) + by / 2 as Long;
                        if (tileMap.containsKey(pidx)) {
                            var ptile: TileUI = tileMap.get(pidx) as TileUI;
                            insert newtile into ptile.covering;
                            newtile.zoomParent = ptile;
                        }
                        insert newtile into tiles;
                    }
                }
            }
        }
    }

    override protected function create(): Node {
        println(width);
        Group { content: bind [tiles] }
    }

}
